import { Modal } from 'antd';
import * as uuid from 'uuid';
import cloneDeep from 'clone-deep';
import { toNumber } from '../utils';
import { getSeatId, getSeat, toJson, toList } from '../helper';
import type { SeatType, SeatDatas, GridType } from '../types';
import type { MoveSeatOpts, MoveDataType, SeatsNumberOpts, DelSeatsOpts, CreateSeatsOpts } from './types';

type GetScrapSeatRsult = {
  key: string;
  scrapSeat: SeatType;
}

// 根据格子获取座位
export const getSeatByGrid = (seats: SeatDatas, grid: GridType) => {
  const seatId = getSeatId(grid);
  const seat = seats[seatId];
  if (seat) return getSeat(seat);
}

// 查找被废弃的座位
const getScrapSeat = (seats: SeatDatas, grid: GridType) => {
  let result: GetScrapSeatRsult | undefined;

  for (const key in seats) {
    const seat = getSeat(seats[key]);
    const orginSeat = seat.orginSeat;
    const scrapSeat = orginSeat || seat;
    if (getSeatId(scrapSeat) === getSeatId(grid)) {
      result = { key, scrapSeat };
      break;
    }
  }
  return result;
}

// 创建座位
export const createSeats = (opts: CreateSeatsOpts) => {
  const { seats, grids, scrapSeats } = opts;
  let changed = false;
  for (const grid of grids) {
    // 查找当前位置是否有被删除过的位置
    const result = getScrapSeat(scrapSeats, grid);
    if (result) {
      changed = true;
      const nextSeat = result.scrapSeat;
      const nextId = getSeatId(nextSeat);
      delete scrapSeats[result.key];
      // 恢复被删除的数据
      seats[nextId] = toJson({
        updated: true,
        id: nextSeat.id,
        row: nextSeat.row,
        column: nextSeat.column,
      });
    } else {
      const id = getSeatId(grid);
      if (!seats[id]) {
        changed = true;
        seats[id] = toJson(grid);
      }
    }
  }
  if (changed) {
    return cloneDeep(seats);
  }
}

// 获取选中的座位
export const getSelectedSeats = (seats: SeatDatas, grids: GridType[]) => {
  const records: SeatDatas = {};
  for (const grid of grids) {
    const id = getSeatId(grid);
    const seat = seats[id];
    if (seat) records[id] = seat;
  }
  return records;
}

// 移动座位
export const moveSeats = (seats: SeatDatas, opts: MoveSeatOpts) => {
  const { row, column, selectedSeats } = opts;

  let errorMsg: string = '';
  const moveDatas: MoveDataType[] = [];

  const rowStep = toNumber(row.step);
  const rowDirection = row.direction;
  const columnStep = toNumber(column.step);
  const columnDirection = column.direction;

  // 先删除
  for (const prevId in selectedSeats) {
    const json = selectedSeats[prevId];
    const prevSeat = getSeat(json);

    let row = prevSeat.row;
    let column = prevSeat.column;

    //向左移动
    if (columnDirection === 'left') {
      column -= columnStep;
    } else {
      column += columnStep;
    }

    if (rowDirection === 'top') {
      row -= rowStep;
    } else {
      row += rowStep;
    }

    if (row < 0) {
      errorMsg = `向上移动的目标位置将超出边界!`;
      break;
    }

    if (column < 0) {
      errorMsg = `向左移动的目标位置将超出边界!`;
      break;
    }

    if (row > opts.maxRow - 1) {
      errorMsg = `向下移动的目标位置将超出边界!`;
      break;
    }

    if (column > opts.maxColumn - 1) {
      errorMsg = `向右移动的目标位置将超出边界!`;
      break;
    }

    const nextGrid = { row, column };
    const res1 = getSeatByGrid(seats, nextGrid);
    const res2 = getSeatByGrid(selectedSeats, nextGrid);

    // 碰撞检查
    if (res1 && !res2) {
      // 删除的就忽略它
      if (!res1.deleted) {
        errorMsg = `移动的目标位置存在其他座位!`;
        break;
      }
    }

    moveDatas.push({
      prevId,
      prevSeat,
      nextGrid
    });
  }

  if (errorMsg) {
    Modal.error({
      title: '移动座位失败',
      content: errorMsg
    });
    return false;
  }

  // 先删除
  moveDatas.forEach(({ prevId }) => delete seats[prevId]);

  moveDatas.forEach(item => {
    const { prevSeat, nextGrid } = item;
    const nextId = getSeatId(nextGrid);
    const newGrid = { ...prevSeat, ...nextGrid };

    // 如果位置存在 id
    if (newGrid.id) {
      //添加座位的原始位置
      if (!newGrid.orginSeat) {
        newGrid.orginSeat = prevSeat;
      }
      newGrid.updated = true;
    }

    seats[nextId] = toJson(newGrid);
  });

  return cloneDeep(seats);
}

// 以排为单位获取列的集合
export const getRowGrids = (seats: SeatDatas) => {
  let pre: SeatType;
  let cols: SeatType[] = [];
  const caches: Array<SeatType[]> = [];
  const lists = toList(seats);

  lists.forEach(seat => {
    const isNext = pre?.row !== seat.row;
    if (isNext) {
      cols = [];
    }
    cols.push(seat);
    if (isNext) {
      caches.push(cols);
    }
    pre = seat;
  });
  return caches;
}

// 座位编号
export const seatsNumber = (seats: SeatDatas, opts: SeatsNumberOpts) => {
  const { row, column, selectedSeats } = opts;
  let rows = getRowGrids(selectedSeats);

  const rowDirection = row.direction;
  const rowStep = toNumber(row.step, 1);
  const rowStartNum = toNumber(row.startNum, 1);

  const columnDirection = column.direction;
  const columnStep = toNumber(column.step, 1);
  const columnStartNum = toNumber(column.startNum, 1);

  // 排从下往上
  if (rowDirection === 'top') {
    rows = [...rows].reverse();
  }

  rows.forEach((grids, rowNum) => {
    // 从右往左
    if (columnDirection === 'left') {
      grids = [...grids].reverse();
    }

    grids.forEach((grid, colNum) => {
      // 编号最小从 1 开始
      const startRow = rowNum + rowStartNum;
      const startCol = colNum + columnStartNum;

      const seatNumber = {
        row: {
          type: row.type,
          prefix: row.prefix,
          number: startRow * rowStep,
        },
        column: {
          type: column.type,
          prefix: column.prefix,
          number: startCol * columnStep,
        }
      }

      const seatId = getSeatId(grid);
      const seat = getSeat(seats[seatId]);

      if (seat) {
        // 存在 id 则为编辑
        if (seat.id) {
          seat.updated = true;
        }
        seat.seatNumber = seatNumber;
        seats[seatId] = toJson(seat);
      }
    });
  });

  return cloneDeep(seats);
}

// 检查是否有编号
export const checkSeatNum = (seats: SeatDatas) => {
  return !!toList(seats).find(item => item.seatNumber);
}

// 删除座位编号
export const delSeatNumber = (seats: SeatDatas, selectedSeats: SeatDatas) => {
  const ids = Object.keys(selectedSeats);
  for (const id of ids) {
    const seat = getSeat(seats[id]);
    // 如果存在 id, 则认为是更新
    if (seat.id) {
      seat.updated = true;
    }
    delete seat.seatNumber;
    seats[id] = toJson(seat);
  }
  return cloneDeep(seats);
}

// 删除座位
export const delSeats = (opts: DelSeatsOpts) => {
  const { seats, scrapSeats, selectedSeats } = opts;
  const ids = Object.keys(selectedSeats);

  for (const id of ids) {
    const seat = getSeat(seats[id]);
    // 如果存在 id
    if (seat.id) {
      delete seats[id];
      scrapSeats[uuid.v4()] = toJson(seat);
    } else {
      delete seats[id];
    }
  }
  return cloneDeep(seats);
}